package virtualinit.util;

import virtualinit.AbstractInit;
import virtualinit.Config;
import virtualinit.InsertTask;

import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.lang.reflect.Array;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicLong;

import static virtualinit.AbstractInit.tbCounts;

/**
 * 程序计时工具 ，支持多任务，开始，暂停，恢复，结束
 * startTime    1
 * <p>
 * pause1       5
 * resume1      7
 * <p>
 * pause2       8
 * resume2      10
 * <p>
 * stop         11
 * time =   11-(2+2) - 1
 */
public class StopWatch {
    Config config = Config.instance;
    private ArrayBlockingQueue<InsertTask.Task> sqlQueue = new ArrayBlockingQueue<>(100);
    public AtomicLong totalCount = new AtomicLong(0);
    public long tipsSize = Integer.parseInt(config.getProperty("tipsSize", 10000_0 + ""));
    ;
    public long lastRecordMs = System.currentTimeMillis();
    public long lastCount;

    public StopWatch() {}

    public StopWatch(ArrayBlockingQueue<InsertTask.Task> sqlQueue) {
        this.sqlQueue = sqlQueue;
    }

    public boolean isStarted() {
        return timerTask.isStarted();
    }

    public boolean isStopped() {
        return timerTask.isStopped();
    }

    public boolean isPaused() {
        return timerTask.isPaused();
    }

    public boolean start() {
        return timerTask.start();
    }

    public long stop() {
        return timerTask.stop();
    }

    public long pause() {
        return timerTask.pause();
    }

    public void resume() {
        timerTask.resume();
    }

    public long getNanoTime() {
        return timerTask.getNanoTime();
    }

    public long getTime() {
        return timerTask.getTime();
    }

    TimerTask timerTask = new TimerTask(Thread.currentThread());

    Map<Thread, TimerTask> threadLocalTimerTask;

    public long record(int update, long startTime) {
        long total = totalCount.get();
        long l = totalCount.addAndGet(update);
        long l1 = l / tipsSize;
        if (l1 > (total / tipsSize)) {
            long time = System.currentTimeMillis() - lastRecordMs;
            double currentRate = (l - lastCount) / (time / 1000D) / 10000D;

            StringBuilder tbInfo = new StringBuilder(1024);
            for (Map.Entry<String, AtomicLong> entry : tbCounts.entrySet()) {
                String key = entry.getKey();
                String channel = key.substring(key.lastIndexOf('-') + 1);
                tbInfo.append(channel).append(':').append(entry.getValue()).append(',');
            }

            System.out.println(String.format("实时:%.3f万/秒 total:%.3f万 总耗时:%s sql耗时:%s sqlQueue:%s:%s %s",
                    currentRate, l / 10000D, TimeUtil.toStr(getTime(), TimeUtil.cnUnitName, ""),
                    System.currentTimeMillis() - startTime, sqlQueue.size(), sqlQueue.remainingCapacity(), tbInfo));
            lastRecordMs = System.currentTimeMillis();
            lastCount = l;
        }
        return l;
    }

    public static void main(String[] args) throws Exception{

        ArrayList<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));
        ListIterator<Integer> it = list.listIterator();


        Iterator<Integer> i = list.iterator();

        while (i.hasNext()) {
            Integer next = i.next();
            i.remove();
        }


    }

    public static class TimerTask {
        static final int INIT = 0; //new
        static final int STARTED = 1; //开始
        static final int STOPPED = 2; //停止
        static final int PAUSED = 3; //暂停
        private String taskName;

        private String threadName; // 线程名
        private long threadId; // 线程id

        private long startTime = System.nanoTime(); // 开始时间
        private long endTime; // 结束时间
        private long relativeStartTime = startTime; // 暂停后的相对开始时间，暂停就像当于把开始时间提前了
        private long pauseTime; // 暂停时间


        private int state = INIT; // 状态

        public TimerTask(Thread currentThread) {
            if (currentThread != null) {
                this.threadId = currentThread.getId();
                this.threadName = currentThread.getName();
                if (this.taskName == null) {
                    this.taskName = this.threadName;
                }
            }
        }

        public TimerTask(String name, Thread currentThread) {
            this(currentThread);
            this.taskName = name;
        }

        public boolean isStarted() {
            return state == STARTED;
        }

        public boolean isStopped() {
            return state == STOPPED;
        }

        public boolean isPaused() {
            return state == PAUSED;
        }

        public boolean start() {
            if (state == INIT || isStopped()) {
                startTime = System.nanoTime();
                relativeStartTime = startTime;
                state = STARTED;
                pauseTime = 0;
                endTime = 0;
                return true;
            }
            return false;
        }

        public long stop() {
            endTime = System.nanoTime();
            resume();
            state = STOPPED;
            return (endTime - relativeStartTime) / 1000000;
        }

        public long pause() {
            if (state == STARTED) {
                state = PAUSED;
                pauseTime = System.nanoTime();
            }
            return getTime();
        }

        public void resume() {
            if (state == PAUSED) {
                state = STARTED;
                relativeStartTime = relativeStartTime + (System.nanoTime() - pauseTime);
            }
        }

        public long getNanoTime() {
            return endTime - relativeStartTime;
        }

        public long getTime() {
            long et = endTime;
            if (isPaused()) {
                et = pauseTime;
            } else if (et == 0) {
                et = System.nanoTime();
            }
            return (et - relativeStartTime) / 1000000;
        }
    }


}
